package BeenChina.PM.Action;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.struts2.ServletActionContext;

import net.sf.json.JSONArray; 

import BeenChina.PM.Model.ModelCalculateBaseInfo;
import BeenChina.PM.Model.ModelCalculateCaseInfo;
import BeenChina.PM.Model.ModelCalculateEmpCalculateInfo;
import BeenChina.PM.Model.ModelUser;
import BeenChina.PM.Service.ServiceFactory;
import BeenChina.PM.Util.EncodeDownLoadFileName;
import BeenChina.PM.Util.ExportInfo;
import BeenChina.PM.Util.ExportToExcel;
import BeenChina.PM.Util.StringUtil;
import BeenChina.PM.Util.xmlSerializer;

import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;

 
public class CalculateQueryAction extends ActionSupport
{   
 
	private static final long serialVersionUID = 1L;
	private String dateTo;
	private List<ModelCalculateBaseInfo>   calculateBaseInfos = new ArrayList<ModelCalculateBaseInfo>();
	private List<ModelCalculateEmpCalculateInfo> calculateEmpCalculateInfos = new ArrayList<ModelCalculateEmpCalculateInfo>();
	private List<ModelCalculateCaseInfo> calculateCaseInfosA = new ArrayList<ModelCalculateCaseInfo>();
	private List<ModelCalculateCaseInfo> calculateCaseInfosB = new ArrayList<ModelCalculateCaseInfo>();
	private Map<String, Object> chartData; 
	private InputStream excelStream;  
	private String fileName;
	private static String EXPORTID = "461";
	private boolean exportExcel; 
	private static final Log log = LogFactory.getLog(CalculateQueryAction.class);
	
	public boolean isExportExcel() {
		return exportExcel;
	}  
	public InputStream getExcelStream() {
		return excelStream;
	}

	public void setExcelStream(InputStream excelStream) {
		this.excelStream = excelStream;
	}

	public String getFileName() throws UnsupportedEncodingException {		
		ServletActionContext.getResponse().setHeader("charset","UTF-8");
		fileName = EncodeDownLoadFileName.encode(ServletActionContext.getRequest(), fileName); 
		return fileName;
	}

	public void setFileName(String fileName) {
		this.fileName = fileName;
	}
	

	public Map<String, Object> getChartData() {
		return chartData;
	}
  
	public void setDateTo(String dateTo) {
		this.dateTo = dateTo;
	}
	
	@Override
	public String execute()	{	
		ModelUser user = (ModelUser) ActionContext.getContext().getSession().get("user");
		if (user!=null)
		  exportExcel = user.concatPermission(EXPORTID);
  		return "load";
	}
	
 

	public List<ModelCalculateBaseInfo>  getBaseData()	throws Exception {
		try{
			
			 if (StringUtil.isDate(dateTo,"yyyy-MM")   )
			 {
				return ServiceFactory.getInstance().getCaseProductionInfoService().selectCalculateBaseInfo(dateTo);			 				
			 }
			 else {
				 return null;
			}			 
		 }
		 catch(Exception exp){
			 throw exp;
		 }		
	}
	
	public List<ModelCalculateEmpCalculateInfo> getEmpCalculateData()	throws Exception {
		try{
			 if (StringUtil.isDate(dateTo,"yyyy-MM")   )
			 {
				 return ServiceFactory.getInstance().getCaseProductionInfoService().selectCalculateEmpCalculateInfo(dateTo);		 				
			 }
			 else {
				 return null;
			}
			 
		 }
		 catch(Exception exp){
			 throw exp;
		 }
		
	}
	
	public List<ModelCalculateCaseInfo> getCalculateCaseInfosA()	throws Exception {
		try{
			 if (StringUtil.isDate(dateTo,"yyyy-MM")   )
			 {
				 return ServiceFactory.getInstance().getCaseProductionInfoService().selectCalculateCaseInfo(dateTo, "発生枚数");		 				
			 }
			 else {
				 return null;
			} 
		 }
		 catch(Exception exp){
			 throw exp;
		 } 
	}
	
	public List<ModelCalculateCaseInfo> getCalculateCaseInfosB()	throws Exception {
		try{
			 if (StringUtil.isDate(dateTo,"yyyy-MM")   )
			 {
				 return ServiceFactory.getInstance().getCaseProductionInfoService().selectCalculateCaseInfo(dateTo, "予測人数");		 				
			 }
			 else {
				 return null;
			} 
		 }
		 catch(Exception exp){
			 throw exp;
		 } 
	}
	
	public String refreshChartData() throws Exception
	 { 
		 this.calculateBaseInfos = getBaseData();
		 this.calculateEmpCalculateInfos = getEmpCalculateData();	
		 this.calculateCaseInfosA = getCalculateCaseInfosA();
		 this.calculateCaseInfosB = getCalculateCaseInfosB();
		 
		 //get chart data
		 JSONArray mapEmpCount = new JSONArray();
		 JSONArray mapMaxDAwayEmp = new JSONArray();
		 JSONArray mapMaxWorkEmp = new JSONArray();
		 JSONArray mapAvgDAwayEmp = new JSONArray(); 
 	
		 
		 if (calculateEmpCalculateInfos !=null && calculateEmpCalculateInfos.size()>0)
		 {
			for (ModelCalculateEmpCalculateInfo model : calculateEmpCalculateInfos) {
				
				JSONArray json = new JSONArray();
				json.add(model.getMonth());
				json.add(model.getEmpCount());
				mapEmpCount.add(json);
				
				json = new JSONArray();				
				json.add(model.getMonth());
				json.add(model.getMaxDAwayEmp());
				mapMaxDAwayEmp.add(json);
				
				
				json = new JSONArray();				
				json.add(model.getMonth());
				json.add(model.getMaxWorkEmp());
				mapMaxWorkEmp.add(json);
				 
				json = new JSONArray();				
				json.add(model.getMonth());
				json.add(model.getAvgDAwayEmp());
				mapAvgDAwayEmp.add(json); 
			}
		 }
		 
		 Map<String, Object> map = new HashMap<String, Object>();  
	     map.put("EmpCount", mapEmpCount);  	     	     
		 map.put("MaxDAwayEmp", mapMaxDAwayEmp); 
		 map.put("MaxWorkEmp", mapMaxWorkEmp);
		 map.put("AvgDAwaySpareEmp", mapAvgDAwayEmp);  
		 
		 
		 map.put("TableTittle", getTittleTable(this.calculateBaseInfos)); 
		 map.put("TableMaster", getMasterTable(this.calculateEmpCalculateInfos));
		 map.put("TableDetailA", getDetailTable(this.calculateCaseInfosA,new DecimalFormat("#")));
		 map.put("TableDetailB", getDetailTable(this.calculateCaseInfosB,new DecimalFormat("#.0")));
		 
		 chartData = map;
	     return Action.SUCCESS;  
	 }
	 
	public JSONArray getTittleTable( List<ModelCalculateBaseInfo> list) throws Exception{
		
		 
		 JSONArray mapTittleTable = new JSONArray();
		 if (list ==null || list.size() ==0 )
		 {
			 return mapTittleTable;
		 }
		 
		 ModelCalculateBaseInfo temp ;
		 JSONArray json = new JSONArray();
		 json.add("計算関連条件設定");
		 json.add("-");
		 mapTittleTable.add(json);
		 
		 json = new JSONArray();
		 json.add("在職オペレータ数 「本番+新規」"); 
		 temp = new ModelCalculateBaseInfo();
		 temp.setCategoryName("EmpCount");
		 json.add(list.get(list.indexOf(temp)).getContent());
		 mapTittleTable.add(json);
		 
		 json = new JSONArray();		 
		 json.add("本番エントリへ投入できるOP数<br>「総-新規」");
		 temp = new ModelCalculateBaseInfo();
		 temp.setCategoryName("UnitEmpCount");
		 json.add(list.get(list.indexOf( temp )).getContent());
		 mapTittleTable.add(json);
		 
		 json = new JSONArray();		 
		 json.add("予想満負荷稼働率");
		 temp = new ModelCalculateBaseInfo();
		 temp.setCategoryName("CalculateUtiliza");
		 json.add(list.get(list.indexOf(temp)).getContent());
		 mapTittleTable.add(json);
		 
		 json = new JSONArray();		 
		 json.add("欠勤率");	
		 temp = new ModelCalculateBaseInfo();
		 temp.setCategoryName("AwayRate");
		 json.add(list.get(list.indexOf(temp)).getContent());
		 mapTittleTable.add(json);
		 
		 json = new JSONArray();		 
		 json.add("他非本番");
		 temp = new ModelCalculateBaseInfo();
		 temp.setCategoryName("NonWorkRate");
		 json.add(list.get(list.indexOf(temp)).getContent());
		 mapTittleTable.add(json);
		 		 
		 
		 return mapTittleTable;
	 }
		 
	public JSONArray getMasterTable(List<ModelCalculateEmpCalculateInfo> list) throws Exception{
		
		 
		 JSONArray mapMasterTable = new JSONArray();
		 if (list ==null || list.size() ==0)
		 {
			 return mapMasterTable;
		 }
		 
		  
		 
		 //init head
		 JSONArray json = new JSONArray();		 
		 //init table head
		 json.add("必要リソース/月分");
		 for (ModelCalculateEmpCalculateInfo model : list) { 
		  json.add(model.getMonth());
		}		 
		 mapMasterTable.add(json);
		 
		 
		 json = new JSONArray(); 
		 json.add("在籍見込み");
		 for (ModelCalculateEmpCalculateInfo model : list) { 
		  json.add(model.getEmpCount());
		} 
		 mapMasterTable.add(json); 
		 
		 json = new JSONArray();		 
		 //init table head
		 json.add("①全案件対応必要要員数 <br>（欠勤・テスト等を除く）");
		 for (ModelCalculateEmpCalculateInfo model : list) { 
		  json.add( model.getMaxWorkEmp());		   
		}		 
		 mapMasterTable.add(json);
		 
		 json = new JSONArray();		 
		 //init table head
		 json.add("①リソース状況「不足/余り」");
		 for (ModelCalculateEmpCalculateInfo model : list) { 
		  json.add( model.getWorkSpareEmp());		   
		}		 
		 mapMasterTable.add(json);
		 

		 json = new JSONArray();		 
		 //init table head
		 json.add("②契約必要要員数（ＭＡＸ対応）<br>（欠勤・テスト等の不稼働を含む）");
		 for (ModelCalculateEmpCalculateInfo model : list) { 
		  json.add( model.getMaxDAwayEmp());		   
		}		 
		 mapMasterTable.add(json);		 
		 
		 json = new JSONArray();		 
		 //init table head
		 json.add("②リソース状況「不足/余り」");
		 for (ModelCalculateEmpCalculateInfo model : list) { 
		  json.add( model.getdAwaySpareEmp());		   
		}		 
		 mapMasterTable.add(json);
 
		 
		 json = new JSONArray();		 
		 //init table head
		 json.add("③契約必要要員数（平均対応）<br>（欠勤・テスト等の不稼働を含む）");
		 for (ModelCalculateEmpCalculateInfo model : list) { 
		  json.add( model.getAvgDAwayEmp());		   
		}		 
		 mapMasterTable.add(json);

		 json = new JSONArray();		 
		 //init table head
		 json.add("③リソース状況「不足/余り」");
		 for (ModelCalculateEmpCalculateInfo model : list) { 
		  json.add( model.getAvgDAwaySpareEmp());		   
		}		 
		 mapMasterTable.add(json);
		 
		 return mapMasterTable;
	 }
	 
	public JSONArray getDetailTable(List<ModelCalculateCaseInfo> list ,DecimalFormat df) throws Exception{
 
		 
		 JSONArray mapDetailTable = new JSONArray();
		 if (list ==null || list.size() ==0)
		 {
			 return mapDetailTable;
		 } 
		 
		 JSONArray jsonFirst = new JSONArray();
		 jsonFirst.add("曜日");
		 jsonFirst.add("-");
		 jsonFirst.add("-");
		 jsonFirst.add("-");
		 jsonFirst.add("-");
		 jsonFirst.add("-");
		 
		 
		 JSONArray json = new JSONArray();		 
		 //init table head
		 json.add("No.");		 
		 json.add("案件");
		 json.add("発生日");
		 json.add("納期");
		 json.add("1枚当たり生産性");
		 json.add("備考");
		 
		 ModelCalculateCaseInfo first = list.get(0);		 
		 
		 
		 
		 for (ModelCalculateCaseInfo model : list) {
			 
			 if (!(model.getCalculateMonth()+ model.getCalculateWeek()).
					 equals( first.getCalculateMonth() + first.getCalculateWeek()) &&
					 model.getCaseName().equals(first.getCaseName()))
			{ 
		  	    //json.add(first.getMonth()   + first.getCalculateWeek() );		 
				json.add(first.getMonth());
		  	    jsonFirst.add(first.getCalculateWeek());
				first = model;
				
			}
			 
		}
	 	// add last item		 
		// json.add(first.getMonth()  + first.getCalculateWeek() );
		 json.add(first.getMonth());
	  	 jsonFirst.add(first.getCalculateWeek());
	  	    
		 mapDetailTable.add(json);
		 mapDetailTable.add(jsonFirst);
		 
		 //init result head
		 first = list.get(0);		 
		 List<ModelCalculateCaseInfo> resultHeader = new ArrayList<ModelCalculateCaseInfo>();
		 for (int i = 0; i < list.size(); i++) {
			 ModelCalculateCaseInfo model = list.get(i);
			 
			 if ( (model.getCalculateMonth() + model.getCalculateWeek())
					 .equals( first.getCalculateMonth() + first.getCalculateWeek())	 )
			  {
				  resultHeader.add(model);
			  }
		}
		 
		 
		 for (int i = 0; i < resultHeader.size(); i++) {
			 ModelCalculateCaseInfo modelH = resultHeader.get(i);
			 
			 json = new JSONArray();	
			 
			 json.add( i+1 );
			 json.add(modelH.getCaseName());
			 json.add(modelH.getOccurDayExplain());
			 json.add(modelH.getDeliveryTime());
			 json.add( modelH.getaVGProduceTime());
			 json.add(modelH.getCaseExplain());
			 
			 for (int j = 0; j < list.size(); j++) {
				 ModelCalculateCaseInfo model = list.get(j); 
				 
				 if ( modelH.getCaseName().equals(model.getCaseName()))   
				 {
					 Double temp = model.getCalculateInfo()==null ? 0 : model.getCalculateInfo();
					 json.add( df.format(temp ));
				 }
			}
			 
			 mapDetailTable.add(json);
		}
		  
 
		 return mapDetailTable;
	 }
	
	public String export() throws Exception{		 
		try{	
			String file=ServletActionContext.getServletContext().getRealPath("WEB-INF/excel/CalculateQuery.xls");  

			this.calculateBaseInfos = getBaseData();
			this.calculateEmpCalculateInfos = getEmpCalculateData();	
			this.calculateCaseInfosA = getCalculateCaseInfosA();
			this.calculateCaseInfosB = getCalculateCaseInfosB();
			 
			Map<String, JSONArray> map = new HashMap<String, JSONArray>();   		 
			map.put("計算関連条件設定", getTittleTable(this.calculateBaseInfos)); 
			map.put("案件対応必要リソース予想状況", getMasterTable(this.calculateEmpCalculateInfos));
			map.put("案件毎の発生予想（枚数）", getDetailTable(this.calculateCaseInfosA,new DecimalFormat("#")));
			map.put("案件対応必要リソース（人数）", getDetailTable(this.calculateCaseInfosB,new DecimalFormat("#.0")));
			
			ByteArrayOutputStream out = new ByteArrayOutputStream(); 		
			this.setFileName("要員計画表_" + this.dateTo);			
			String infoFile=ServletActionContext.getServletContext().getRealPath("WEB-INF/excel/CalculateQuery.xml");
			List<ExportInfo> infoList = (new xmlSerializer<List<ExportInfo>>()).read(infoFile);
			
			ExportToExcel.export(file, map, infoList,out);
			
			setExcelStream(new ByteArrayInputStream(out.toByteArray()));	   			   			      
			out.close();
		
			return ActionSupport.SUCCESS;
		}
		catch(Exception exp){
			log.error(exp);
			return ActionSupport.ERROR;
		}		
	}		
}
